#pragma once


#include <iostream>
#include <memory>
#include <string>
#include <functional>
#include <thread>
#include <stdint.h>


#include "asio.hpp"
#include "nwbaseconnection.h"
#include "networkutil_common_def.h"


namespace NetworkUtil {


class NetworkUtil_DllExport TcpClient : public BaseConnection/*, public std::enable_shared_from_this<TcpClient>*/
{
public:
    TcpClient() {}
    TcpClient(const ConnectionConfigInfo& stConnCfgInfo);
    ~TcpClient() override;

    void setRecvCallbackFunc(std::function<void(const std::string& strDataBuf)> pfnRecvCallback);

    void init() override;
    void deinit() override;

    uint32_t read(char* pDataBuf, uint32_t ui32DataBufLen);
    uint32_t read(std::string& strDataBuf);

    uint32_t write(const char* pDataBuf, uint32_t ui32DataBufLen);
    uint32_t write(const std::string& strDataBuf);

    std::string remoteInfo();

private:
    bool connect();
    void onRecvDataProcess();
    void reconnectToServer();

    void asyncRead();

private:
    volatile bool m_bConnected = false;
    volatile bool m_bReconnecting = false;
    std::shared_ptr<asio::ip::tcp::socket> m_sp4ObjSocket = nullptr;
    std::shared_ptr<std::thread> m_sp4thRecv = nullptr;
    std::shared_ptr<std::thread> m_sp4thReconn = nullptr;

    char* m_pReadBuffer = nullptr;

    std::function<void(const std::string& strDataBuf)> m_pfnRecvCallback = nullptr;
    asio::ip::tcp::endpoint m_objRemoteEndPoint;
};


} // namespace NetworkUtil

